package com.digital.library.common.utils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DateUtil {

    public static final String DATE_TYPE1 = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_TYPE2 = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_TYPE3 = "yyyyMMddHHmmssSSS";
    public static final String DATE_TYPE4 = "yyyyMMddHHmmss";
    public static final String DATE_TYPE5 = "yyyy-MM-dd";
    public static final String DATE_TYPE6 = "yy-MM-dd-HH-mm-ss";
    public static final String DATE_TYPE7 = "yyyy-MM-dd HH:mm";
    public static final String DATE_TYPE8 = "yyyyMMdd";
    public static final String DATE_TYPE9 = "yyyy-M-d H:m:s:S";
    public static final String DATE_TYPE10 = "yyyyMMddHHmm";
    public static final String DATE_TYPE11 = "yyyy-M-d H:m:s";
    public static final String DATE_TYPE12 = "yy-MM-dd HH:mm:ss";
    public static final String DATE_TYPE13 = "yyyy/MM/dd HH:mm:ss";
    public static final String DATE_TYPE14 = "MM-dd HH:mm:ss";
    public static final String DATE_TYPE15 = "yyyy年MM月dd日 HH:mm";
    public static final String DATE_TYPE16 = "MM月dd日 HH:mm";
    public static final String DATE_TYPE17 = "yyyy.MM.dd";
    public static final String DATE_TYPE18 = "yyyy";
    public static final String DATE_TYPE19 = "MM";
    public static final String DATE_TYPE20 = "dd";
    public static final String DATE_TYPE21 = "HH";

    public static TimeZone timeZoneChina = TimeZone.getTimeZone("Asia/Shanghai");// 获取时区
    public static void main(String[] args) {
        //System.out.print(getDateFromStr("2016-12-17", DATE_TYPE5).getTime());

//		Date d = new Date();
//		d.setTime(1495430376778l);
//		System.out.print(dateToString(d, DATE_TYPE2));
//		System.err.println(getSystemDate(DATE_TYPE5));
//		System.err.println(getFirstDateOfGivenMonth("2016-12-02", DATE_TYPE5));
        System.err.println(getBefore3monthTimeStampFromNow());
    }
    /**
     * 获取指定日期当月的第一天
     * @param dateStr 时间格式
     * @param format  显示格式
     * @return 当月的第一天日期
     */
    public static String getFirstDateOfGivenMonth(String dateStr,String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date;
        try {
            date = sdf.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH,1);
            calendar.add(Calendar.MONTH,0);
            return sdf.format(calendar.getTime());
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取指定日期下个月的第一天
     * @param dateStr 时间格式
     * @param format 显示格式
     * @return  下个月的第一天日期
     */
    public static String getFirstDateOfNextMonth(String dateStr,String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            Date date = sdf.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH,1);
            calendar.add(Calendar.MONTH, 1);
            return sdf.format(calendar.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 日期转字符串
     * @param date 日期
     * @param pattern 格式
     * @return
     */
    public static String dateToString(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            return sdf.format(date);
        }
        return "";
    }

    /**
     * 时间戳字符串转时间格式
     * @param timestamp
     * @param format
     * @return
     */
    public static String timestampToDateStr(String timestamp, String format){
        Date d = new Date();
        d.setTime(Long.parseLong(timestamp));
        return getFormatDate(d,format);
    }
    /**
     * 日期转字符串
     * @param date
     * @return
     */
    public static String dateToString(Date date) {
        return dateToString(date, "yyyy-MM-dd hh:mm:ss");
    }
    /**
     * 获取当前时间
     * @param type 指定格式
     * @return
     */
    public static String getSystemDate(String type) {

        // 指定格式
        DateFormat date_format = new SimpleDateFormat(type);
        date_format.setTimeZone(timeZoneChina);

        // 范围指定格式的字符串
        return date_format.format(new Date());
    }
    /**
     * 获取当前时间
     * 指定格式
     * @return
     */
    public static Date getSystemDate() {

        // 指定格式
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(timeZoneChina);

        // 范围指定格式的字符串
        return calendar.getTime();
    }

    /***************************************************************************
     * 时间运算
     * @param date 运算前时间
     * @param min add的分钟数
     * @return
     */
    public static Date AddMin(Date date, int min) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, min);
        return cal.getTime();
    }

    /**
     * 天数加减
     * @param date 运算前时间
     * @param days 天数
     * @return
     */
    public static Date addDay(Date date, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, days);
        return cal.getTime();
    }

    /**
     * 月数加减
     * @param date 运算前时间
     * @param months 月数
     * @return
     */
    public static Date addMonth(Date date, int months) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, months);
        return cal.getTime();
    }

    /**
     * 年数加减
     * @param date 运算前时间
     * @param years 年数
     * @return
     */
    public static Date addYear(Date date, int years) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, years);
        return cal.getTime();
    }

    /***************************************************************************
     * 时间运算
     *
     * @param date 运算前时间
     * @param value add的值
     * @return
     */
    public static Date AddTime(Date date, int value, int type) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(type, value);
        return cal.getTime();
    }

    /***************************************************************************
     * 时间运算 (月份加算)
     *
     * @param dateStr 运算前时间
     * @param format add的值
     * @return String
     */
    public static String AddMonth(String dateStr, String format, int mon) {
        DateFormat dateFmt = new SimpleDateFormat(format);
        dateFmt.setTimeZone(timeZoneChina);
        Date tmpDate;

        try {
            tmpDate = dateFmt.parse(dateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(tmpDate);
            cal.add(Calendar.MONTH, mon);

            return dateFmt.format(cal.getTime());

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
    }

    /***************************************************************************
     * 取得月的最后一天
     *
     * @param dateStr 日期
     * @param fromFmt 日期格式
     * @return String 参数日期所在月份的最后一天
     */
    public static String getMonthLastDay(String dateStr, String fromFmt,
                                         String toFmt) {
        DateFormat dateFmt = new SimpleDateFormat(fromFmt);
        dateFmt.setTimeZone(timeZoneChina);
        Date tmpDate;

        try {
            tmpDate = dateFmt.parse(dateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(tmpDate);
            cal.set(Calendar.DAY_OF_MONTH, cal
                    .getActualMaximum(Calendar.DAY_OF_MONTH));

            DateFormat dateToFmt = new SimpleDateFormat(toFmt);
            dateToFmt.setTimeZone(timeZoneChina);
            return dateToFmt.format(cal.getTime());
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 时间转化
     *
     * @param dateStr
     * @param fromType
     * @param toType
     * @return
     */
    public static String getFormatDate(String dateStr, String fromType,
                                       String toType) {

        try {
            DateFormat dateFromFmt = new SimpleDateFormat(fromType);
            dateFromFmt.setTimeZone(timeZoneChina);
            DateFormat dateToFmt = new SimpleDateFormat(toType);
            dateToFmt.setTimeZone(timeZoneChina);

            // 非空检查
            if (dateStr == null || dateStr.equals("")) {
                return "";
            } else {
                Date tmpDate = dateFromFmt.parse(dateStr);

                if (dateFromFmt.format(tmpDate).equals(dateStr)) {
                    return dateToFmt.format(tmpDate);
                } else {
                    return "";
                }
            }
        } catch (Exception e) {
            return "";
        }
    }

    public static String getFormatDate(Date date, String toType) {

        try {
            DateFormat dateToFmt = new SimpleDateFormat(toType);
            dateToFmt.setTimeZone(timeZoneChina);
            // 非空检查
            if (date == null) {
                return "";
            } else {
                return dateToFmt.format(date);
            }
        } catch (Exception e) {
            return "";
        }
    }
    public static String getFormatDate(Date date, String toType,TimeZone timeZone) {

        try {
            DateFormat dateToFmt = new SimpleDateFormat(toType);
            dateToFmt.setTimeZone(timeZone);
            // 非空检查
            if (date == null) {
                return "";
            } else {
                return dateToFmt.format(date);
            }
        } catch (Exception e) {
            return "";
        }
    }
    /* *
     * 获取当前时间对应的3个月前的时间戳
     */
    public static long getBefore3monthTimeStampFromNow(){
        long before3Month=0L;
        Date dNow = new Date();   //当前时间
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(dNow);//把当前时间赋给日历
        calendar.add(Calendar.MONTH, -3);  //设置为前3月
        before3Month = calendar.getTime().getTime();   //得到前3月的时间时间戳

//		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置时间格式
//		String defaultStartDate = sdf.format(dBefore);    //格式化前3月的时间
//		System.out.println(before3Month+"三个月之前时间======="+defaultStartDate);
        return before3Month;
    }
    /* *
     * string 日期类型转化未date
     */
    public static Date getDateFromStr(String dateStr, String fromType) throws ParseException{
        DateFormat dateFromFmt = new SimpleDateFormat(fromType);
        dateFromFmt.setTimeZone(timeZoneChina);
        dateFromFmt.setLenient(false);
        return dateFromFmt.parse(dateStr);
    }
    public static Date getDateFromStr(String dateStr, String fromType,TimeZone timeZone) {

        try {
            DateFormat dateFromFmt = new SimpleDateFormat(fromType);
            dateFromFmt.setTimeZone(timeZone);

            return dateFromFmt.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }


    public static boolean isValidDate(String str,String fromFmt) {
        boolean convertSuccess=true;
        SimpleDateFormat format = new SimpleDateFormat(fromFmt);
        try {
            // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            // e.printStackTrace();
            convertSuccess=false;
        }
        return convertSuccess;
    }

    /**
     * 返回天数差
     * @param early
     * @param late
     * @return
     */
    public static int daysBetween(Date early, Date late) {
        Calendar calst = Calendar.getInstance();
        Calendar caled = Calendar.getInstance();
        calst.setTime(early);
        caled.setTime(late);
        //得到两个日期相差的小时数
        float days = (( (caled.getTime().getTime() / 1000) - (calst.getTime().getTime() / 1000)) / 3600f/24f);
        return (int) Math.ceil(days);
    }
    /**
     * 返回两个日期相差的小时数
     * @param early
     * @param late
     * @return BedDecimal 四舍五入保留两位小数
     */
    public static BigDecimal hoursBetween(Date early, Date late) {
        Calendar calst = Calendar.getInstance();
        Calendar caled = Calendar.getInstance();
        calst.setTime(early);
        caled.setTime(late);
        //得到两个日期相差的小时数
        float hours = ( (caled.getTime().getTime() / 1000) - (calst.getTime().getTime() / 1000)) / 3600f;
        return new BigDecimal(hours).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 返回两个日期相差的分钟数
     * @param early
     * @param late
     * @return BedDecimal 四舍五入不保留小数位
     */
    public static BigDecimal MinutesBetween(Date early, Date late) {
        Calendar calst = Calendar.getInstance();
        Calendar caled = Calendar.getInstance();
        calst.setTime(early);
        caled.setTime(late);
        //得到两个日期相差的小时数
        float minutes = ( (caled.getTime().getTime() / 1000) - (calst.getTime().getTime() / 1000)) / 60f;
        return new BigDecimal(minutes).setScale(0, BigDecimal.ROUND_HALF_UP);
    }

    //API调用者传递时间戳，为时间转换为毫秒的值，也就是 从1970年1月1日起至今的时间转换为毫秒，默认15分钟 内有效
    public static int ValidTimestamp(long timestamp){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        Calendar now = Calendar.getInstance();
        now.setTime(new Date());
        Calendar valid = Calendar.getInstance();
        valid.setTime(DateUtil.AddMin(calendar.getTime(), 15));
        return valid.compareTo(now);
    }
}
